package betower

import (
	"context"
	"encoding/json"
	"go.uber.org/zap"
	"wzgames/internal/codec/sfs"
	"wzgames/internal/constant"
	"wzgames/internal/model/aviatorp"
	"wzgames/internal/model/gamep"
	"wzgames/internal/model/roulettep"
	"wzgames/internal/model/statement"
	"wzgames/internal/response"
	"wzgames/pkg/logger"
	"wzgames/pkg/server/http/types"
	"wzgames/pkg/utils/byteutil"
	"wzgames/pkg/utils/calcutil"
	"wzgames/pkg/utils/stringutil"
)

type BetTowerService struct {
}

func NewBetTowerService() *BetTowerService {
	return &BetTowerService{}
}

// QueryStatements 流水查询
func (s *BetTowerService) QueryStatements(ctx context.Context, req *statement.StmReq, res *statement.StmRes) error {
	code, data := StmMgr().QueryStatements(req)
	res.Code = int32(code)
	if code == 0 {
		l := len(data)
		last := req.VIdx
		if l > 0 {
			lastVal := data[l-1]
			last = lastVal.VIdx
		}
		if data == nil {
			data = []*statement.BetResult{}
		}
		rs := &types.Response{
			Code: 200,
			Data: statement.QueryResult{
				Last:  last,
				Count: int64(l),
				Per:   req.Per,
				Data:  data,
			},
		}
		b, err := json.Marshal(rs)
		if err != nil {
			logger.Error("[BetTower] query statements fail on json.Marshal result", zap.Int64("AgtId", req.AgtId), zap.Int32("Per", req.Per), zap.Int64("Start", req.Start), zap.Int64("End", req.End), zap.Error(err))
			res.Code = int32(response.ErrInternal)
		} else {
			res.Data = b
		}
	}

	return nil
}

// QueryUserBets 获取玩家的投注信息
func (s *BetTowerService) QueryUserBets(ctx context.Context, req *statement.StmUserReq, res *statement.StmRes) error {
	code, data := StmMgr().QueryUserStatements(req)
	res.Code = int32(code)
	if code == 0 && data != nil {
		xw := sfs.XWriter{}
		defer xw.Reset()
		xw.WriteUShort(uint16(2))
		xw.WriteStringS(sfs.CmdKey, constant.ResponseGetHistory)
		xw.WriteSfsObjectPre(sfs.ParamId, uint16(3))
		xw.WriteShortS(sfs.KeyCode, response.CSuccess)
		l := len(data)
		xw.WriteLongS(constant.KeyAmountOfRounds, int64(l))

		paramN := uint16(8)
		if req.GameId == gamep.AviatorGameId {
			paramN = 10
		}
		xw.WriteSfsArrayPre(constant.KeyData, uint16(l))
		for _, bet := range data {
			xw.WriteUByte(sfs.SfsObject)
			xw.WriteUShort(paramN)
			betAmt, _ := stringutil.ToFloat64(bet.BetAmt, 0)
			winAmt, _ := stringutil.ToFloat64(bet.WinAmt, 0)
			payout, _ := stringutil.ToFloat64(calcutil.AmountDecimalPointCut(bet.Payout, req.Precision), 0)
			xw.WriteDoubleS(constant.KeyBet, betAmt)
			xw.WriteDoubleS(constant.KeyWinAmount, winAmt)
			xw.WriteDoubleS(constant.KeyPayout, payout)
			xw.WriteBoolS(constant.KeyIsFreeBetGame, bet.FreeBet)
			xw.WriteStringS(constant.KeyCurrency, bet.Curr)
			xw.WriteLongS(constant.KeyTime, bet.BetTime)
			xw.WriteBoolS(constant.KeyWin, response.IfWin(bet.Win))
			if req.GameId == gamep.AviatorGameId {
				avBet := &statement.AviatorBetInfo{}
				_ = json.Unmarshal(byteutil.StringToSliceByte(bet.Detail), avBet)
				xw.WriteLongS(constant.KeyRoundId, bet.RoundId)
				xw.WriteLongS(constant.KeyRoundBetId, int64(bet.BetId))
				xw.WriteDoubleS(constant.KeyMaxMultiplier, avBet.Result)
			} else {
				xw.WriteLongS(constant.KeyRoundId, int64(bet.BetId))
			}
		}
		res.Data = xw.Data()
	}

	return nil
}

// QueryUserBetDetail 玩家投注详情
func (s *BetTowerService) QueryUserBetDetail(ctx context.Context, req *statement.StmBetReq, res *statement.StmBetRes) error {
	code, data := StmMgr().QueryUserStatement(req)
	res.Code = int32(code)
	if code == 0 && data != nil {
		res.Data = &statement.BetRetProtoSimple{
			BetId:   data.BetId,
			RoundId: data.RoundId,
			Curr:    data.Curr,
			FreeBet: data.FreeBet,
			Win:     data.Win,
			BetAmt:  data.BetAmt,
			WinAmt:  data.WinAmt,
			Payout:  data.Payout,
			BetTime: data.BetTime,
			Detail:  data.Detail,
		}
	}
	return nil
}

// AviatorRoundFairness 小飞机轮次详情
func (s *BetTowerService) AviatorRoundFairness(ctx context.Context, req *aviatorp.AvtRoundFairnessReq, res *aviatorp.AvtRoundFairnessRes) error {
	code, data := StmMgr().QueryAviatorRoundFairness(req)
	res.Code = int32(code)
	if code == 0 && data != nil {
		res.Data = data
	}
	return nil
}

// RouletteRoundFairness 新轮盘轮次详情
func (s *BetTowerService) RouletteRoundFairness(ctx context.Context, req *roulettep.RouRoundReq, res *roulettep.RouRoundRes) error {
	code, data := StmMgr().QueryRouletteRoundFairness(req)
	res.Code = int32(code)
	if code == 0 && data != nil {
		res.Data = data
	}
	return nil
}
